﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Media;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using DonnetSpeech;

namespace WCFMINERP.COM
{
	public class Speech {
		public Speech() {
			dlSpeak = SpeekMsg; //发音
			speakThread = new Thread(new ThreadStart(SpeakMsg));

			speakThread.Start();

			
		}
		
		private Dictionary<string, MemoryStream> fileMemoryStreams = new Dictionary<string, MemoryStream>();
		private SpeekMsgDelegate dlSpeak; //发音
		private Thread speakThread = null;
		private Thread speakThreadFemPian = null;
		private Thread tesThread = null;
		private Queue SpeakQueue = new Queue();
		private Queue speakFenPianQueue = new Queue();
		private SpVoice Voice = new SpVoice();
		private SpeechVoiceSpeakFlags SpFlags;
		private SoundPlayer sp;

		private delegate void SpeekMsgDelegate(string strMsg, bool isNeedReadCompleted);

		private struct SpeekMsgStruct {
			public string msg { get; set; }
			public bool isNeedReadCompleted;
			public string gridName { get; set; }
		}

		private void SpeakMsg() {
			while (true) {
				if (SpeakQueue.Count > 0) {
					SpeekMsgStruct currMsgStruct = (SpeekMsgStruct) SpeakQueue.Dequeue();
					SpeekMsg(currMsgStruct.msg, currMsgStruct.isNeedReadCompleted);
				}
				Thread.Sleep(100);
			}
		}
		private void SpeakMsg2() {
			while (true) {
				if (speakFenPianQueue.Count > 0) {
					SpeekMsgStruct currMsgStruct = (SpeekMsgStruct) speakFenPianQueue.Dequeue();
					SpeekMsgWav(currMsgStruct.gridName, currMsgStruct.msg);
				}
				Thread.Sleep(100);
			}
		}
		/// <summary>
		///     发音
		/// </summary>
		/// <param name="strMsg"></param>
		private void SpeekMsg(string strMsg, bool isNeedReadCompleted) {
			try {
				string gridName = strMsg.Split(new char[] {
															','
														})[0];

				//Application.DoEvents();            
				if (isNeedReadCompleted) {
					Voice.Priority = SpeechVoicePriority.SVPAlert;
					SpFlags = SpeechVoiceSpeakFlags.SVSFDefault;
				}
				else {
					SpFlags = SpeechVoiceSpeakFlags.SVSFlagsAsync;
				}
				Voice.Speak(strMsg.Substring(1), SpFlags); //将A去掉直接读格子号
			}
			catch (Exception) {
			}
		}
		private void SpeekMsg(string strMsg) {
			Voice.Speak(strMsg, SpeechVoiceSpeakFlags.SVSFDefault);
		}
		public void Speak(string Msg) {
			SpeakQueue.Enqueue(new SpeekMsgStruct() {msg = " " + Msg, isNeedReadCompleted = true});
		}
		public void Speak(string Msg, bool isComplete) {
			SpeakQueue.Enqueue(new SpeekMsgStruct() {msg = Msg, isNeedReadCompleted = isComplete});
		}
		/// <summary>
		///     wav 格式报格子
		/// </summary>
		/// <param name="inGridName">格子号</param>
		/// <param name="strMsg">其他信息</param>
		private void SpeekMsgWav(string inGridName, string strMsg) {
			try {
				SpFlags = SpeechVoiceSpeakFlags.SVSFlagsAsync;
				char[] inArrStrings = inGridName.ToArray();
				MemoryStream memory;
				foreach(char c in inArrStrings) {
					string num = string.Join("", c);
					fileMemoryStreams.TryGetValue(num + ".wav", out memory);
					if (null != memory) {
						sp = new SoundPlayer(memory);
						//sp.Play();
						memory.Position = 0;
						sp.Stream = null;
						sp.Stream = memory;
						sp.Load();
						sp.PlaySync();
					}
				}
				if (!string.IsNullOrEmpty(strMsg)) {
					Voice.Speak(strMsg, SpFlags);
				}
			}
			catch (Exception) {
			}
		}
		[DllImport("winmm.DLL", EntryPoint = "PlaySound", SetLastError = true, CharSet = CharSet.Unicode, ThrowOnUnmappableChar = true)]
		private static extern bool PlaySound(string szSound, System.IntPtr hMod, PlaySoundFlags flags);

		[System.Flags]
		private enum PlaySoundFlags : int {
			SND_SYNC = 0x0000, //同步播放声音，在播放完后PlaySound函数才返回
			SND_ASYNC = 0x0001, //用异步方式播放声音，PlaySound函数在开始播放后立即返回
			SND_NODEFAULT = 0x0002, //不播放缺省声音，若无此标志，则PlaySound在没找到声音时会播放缺省声音
			SND_LOOP = 0x0008, //重复播放声音，必须与SND_ASYNC标志一块使用
			SND_NOSTOP = 0x0010, //PlaySound不打断原来的声音播出并立即返回FALSE
			SND_NOWAIT = 0x00002000, //如果驱动程序正忙则函数就不播放声音并立即返回
			SND_FILENAME = 0x00020000, //pszSound参数指定了WAVE文件名
			SND_RESOURCE = 0x00040004 //pszSound参数是WAVE资源的标识符，这时要用到hmod参数
		}

		private void runSound(string inFile) {
			PlaySound(inFile, IntPtr.Zero, PlaySoundFlags.SND_ASYNC);
		}
        //public void SpeakWav(string gridNum, string Msg) {
        //    speakFenPianQueue.Enqueue(new SpeekMsgStruct() {msg = " " + Msg, isNeedReadCompleted = true, gridName = gridNum});
        //}
	}
}
